/**
 * 树状图、横向、可编辑
 * @author zxy
 * @date  2021-04-15
 */
import React from 'react';
import PropTypes from 'prop-types';
import ReactEcharts from 'echarts-for-react';
import { Spin } from 'antd';
import { NoDataC } from '../../other';
import Color from '../../../css/colors';

class TreeVEditChartsC extends React.Component {
  // 入参默认值设置
  static defaultProps = {
    height: '100%', // 图形高度默认为父节点的100%
    width: '100%', // 图形宽度默认为父节点的100%
    title: '',
    data: undefined,
    colors: Color.echartItems, // 默认系统色
    depth: undefined, // 树图展开层级
    selectedOnChange: () => {}, // 抛出节点变更事件
    initNode: undefined, // 默认无初始化数据
    onRef: () => {}, // 本组件的引用
  };

  state = {
    latestId: undefined, // 最后一次点击的node的ID
    treeData: undefined, // 树数据源
  };

  componentDidMount() {
    // 父组件对本组件的引用
    this.props.onRef(this);

    // 同步初始化树结构
    this.setState(
      {
        treeData: this.props.data,
        latestId: undefined,
      },
      () => {
        // 同步初始化默认选中节点
        if (this.props.initNode != undefined) {
          this.click(this.props.initNode);
        }
      },
    );
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    const treeDataT = prevProps.data ? JSON.stringify(prevProps.data) : '';
    const treeDataN = this.props.data ? JSON.stringify(this.props.data) : '';
    if (treeDataT != treeDataN) {
      this.setState(
        {
          treeData: this.props.data,
          latestId: undefined,
        },
        () => {
          if (this.props.initNode != undefined) {
            this.click(this.props.initNode);
          }
        },
      );
    }
  }

  // 提供给父节点调用，设置选中节点，入参结构：{value: "code1", name: "xxxxxx组合1"}
  selectNode = (e) => {
    this.click(e);
  };

  // 返回option
  getOption = () => {
    const { title, data, colors, depth } = this.props;

    return {
      // 调色盘颜色列表
      color: colors,
      backgroundColor: Color.echartItems.bgColor, // echarts整个画布的背景色
      // 主标题和副标题
      title: {
        show: !!title,
        left: '20',
        top: 0,
        text: title,
        textStyle: {
          color: Color.echartItems.title,
          fontSize: 14,
          fontWeight: 'normal',
          lineHeight: 20,
        },
      },
      // 提示信息
      tooltip: {
        show: false,
      },
      series: {
        type: 'tree',
        orient: 'vertical', // 纵向展示
        top: 80,
        left: 15,
        bottom: 80,
        right: 15,
        initialTreeDepth: depth,
        symbolSize: 15,
        symbol:
          'image://',
        label: {
          show: true,
          backgroundColor: Color.echartItems.treeTextBg,
          padding: 0,
          distance: 30,
          position: 'top',
          verticalAlign: 'middle', // 垂直居中
          align: 'center', // 文字水平居中
          borderWidth: 0.2,
          borderColor: Color.echartItems.treeBorder,
          formatter: (params) => {
            return `{wenzi1|${params.name}}\n{wenzi2|${params.value}}`;
          },
          textStyle: {
            fontSize: 14,
          },
          rich: {
            wenzi1: {
              color: Color.echartItems.treeText,
              fontSize: 14,
              align: 'left',
              padding: [0, 20, 10, 20],
            },
            wenzi2: {
              color: Color.echartItems.treeText,
              fontSize: 14,
              align: 'left',
              padding: [10, 20, 5, 20],
            },
            select1: {
              color: colors.treeSelectColor,
              fontSize: 14,
              align: 'left',
              padding: [0, 20, 10, 20],
            },
            select2: {
              color: colors.treeSelectColor,
              fontSize: 14,
              align: 'left',
              padding: [10, 20, 5, 20],
            },
          },
        },
        // 叶子节点位置位于下方
        leaves: {
          label: {
            position: 'bottom',
            verticalAlign: 'middle',
            align: 'center',
          },
        },
        expandAndCollapse: false, // 点击节点，不执行展开/收起
        data,
      },
    };
  };

  // 遍历找到指定节点
  find = undefined;

  findNode = (nodeId, node) => {
    node &&
      node.forEach((element) => {
        if (element.value == nodeId) {
          this.find = element;
        } else if (element.children && element.children.length > 0) {
          this.findNode(nodeId, element.children, find);
        }
      });
  };

  // 点击节点
  click = (e) => {
    // 遍历找到data中上一个选中的节点，变更该节点为非选中状态
    this.find = undefined;
    this.findNode(this.state.latestId, this.state.treeData);
    if (this.find) {
      delete this.find.label;
    }

    // 遍历找到data中的该节点，变更该节点样式为选中状态
    this.find = undefined;
    this.findNode(e.value, this.state.treeData);
    if (this.find) {
      this.find.label = {
        formatter: (params) => {
          return `{select1|${params.name}}\n{select2|${params.value}}`;
        },
        backgroundColor: Color.echartItems.treeSelectBg,
      };
    }

    this.setState({
      treeData: this.state.treeData,
      latestId: e.value,
    });

    this.props.selectedOnChange({ value: e.value, name: e.name });
  };

  render() {
    const { width, height } = this.props;
    const { treeData } = this.state;

    return (
      <div style={{ width }}>
        <Spin spinning={!treeData} tip='加载中...'>
          {treeData ? (
            treeData.length > 0 ? (
              <ReactEcharts
                option={this.getOption()}
                style={{ height, width }}
                // 是否不跟之前设置的 option 进行合并，默认为 false，即合并。
                notMerge={true}
                onEvents={{
                  click: this.click,
                }}
              />
            ) : (
              <NoDataC />
            )
          ) : (
            <div style={{ height, width }}></div>
          )}
        </Spin>
      </div>
    );
  }
}

/*
 备注：
   当data值为null或undefined时，显示loading状态
   当data值为空数组[]时，显示“暂无数据”
   当data值为有值的数组时，正常实现图形
 */
TreeVEditChartsC.propsTypes = {
  height: PropTypes.oneOfType([
    // （必填）图表高度（百分比、数值、auto(自动根据图例数量计算高度)）
    PropTypes.string,
    PropTypes.number,
  ]),
  width: PropTypes.oneOfType([
    // 图表宽度（百分比或数值）
    PropTypes.string,
    PropTypes.number,
  ]),
  title: PropTypes.string, // 名称
  data: PropTypes.array, // （必填）树形结构数据[name:'', value:'xx', children:[]]
  selectedOnChange: PropTypes.func, // 抛出点击事件（value和name）
  initNode: PropTypes.object, // 初始化选中某节点，格式为：{value: "code1", name: "xxxxxx组合1"}
  onRef: PropTypes.func, // 本组件的引用（可用来父组件调用内部方法）
};

export default TreeVEditChartsC;
